home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
076-100
/
disk_091
/
man
/
adl.doc
< prev
next >
Wrap
Text File
|
1992-05-06
|
114KB
|
5,413 lines
The ADL Programmer's Reference Manual
Tim Brengle
Ross Cunniff
Hewlett-Packard Company
Cupertino, California 95014
ABSTRACT
ADL (which stands for "Adventure Definition
Language") is a programming language and run-time
environment designed for the convenient implemen-
tation of Adventure-like games. This document
describes ADL and is intended for the use of a
programmer who wishes to create such a game.
The authors would like to acknowledge the
tremendous influence of the earlier language DDL
from which ADL was derived. DDL was created in
1981 by Bruce Adler, Chris Kostanick, Michael
Stein, Michael Urban, and Warren Usui, then
members of the UCLA Computer Club. For informa-
tion on DDL, please consult the document "A Brief
Description of UCLA Dungeon Definition Language
(DDL)" written by the creators of DDL and avail-
able from the University of California.
June 19, 1987
c 1987 Ross Cunniff and Tim Brengle
The ADL Programmer's Reference Manual
Tim Brengle
Ross Cunniff
Hewlett-Packard Company
Cupertino, California 95014
1. Introduction
Computer games have existed for nearly as long as com-
puters have existed. One of the most popular computer pro-
grams of all time is Adventure. In Adventure, the player is
placed inside a world which exists only in the memory of the
computer (and the mind of the player). The player interacts
with this world by means of English-like sentences. Objects
that the player finds may be taken, opened, closed, tasted,
thrown, and otherwise manipulated.
Previously, most programmers attempting to write their
own Adventure-like game have been bogged down by such
trivial details as implementing a parser for player input,
properly responding to the player's commands, and dealing
with the passage of time. ADL is intended to relieve the
programmer of such worries and to allow the programmer to
concentrate on the important details of the imaginary world.
The following is a short excerpt from the play of a game
which was written in ADL:
Red room.
You are in a large room which is illuminated by a bright red glow.
Exits lie to the east and south.
> Go east.
Green room.
You are in a smallish room which is illuminated by a pleasant green
glow. The only exit is to the west.
There is a robot here.
> west
Red room.
> s
Blue room.
You are in a tiny room which is barely illuminated by a dim blue
glow. There is an exit to the north, and you seem to make out
something on the floor. There is a button on the wall. Above the
button is a sign that reads:
DANGER!
c 1987 Ross Cunniff and Tim Brengle
- 2 -
HIGH VOLTAGE!
> n
Red room.
> e
Green room.
You can see:
a robot
> Tell the robot "Go west then south. Push the button then go north."
"Sure thing, Boss."
The robot exits to the west.
Notice that this script demonstrates powerful features
not present in many other Adventure-like games. This docu-
ment will describe the utilities and "tricks" necessary to
write games such as the above.
c 1987 Ross Cunniff and Tim Brengle
- 3 -
2. ADL Data types
Structured data types are the heart of any structured
language. ADL is not lacking in structured data types. It
is through the proper definition of specific instances of
these data types that the ADL programmer defines a scenario.
Note that all data types in ADL are represented by sixteen-
bit integer IDs. Although there is little facility for pro-
ducing user-defined data types, the power of the existing
set makes it unlikely that such would be required for any
reasonable scenario.
2.1. Objects
As in most Adventure-like games, the most important
data type in ADL is the Object. An object in real life can
be a person, place, or thing. ADL models the world in the
same way. Any Object encountered by the player is
represented by this type, as are all locations in the
scenario. Indeed, there can be Objects associated with peo-
ple (more on that later). Notice that ADL treats all
Objects uniformly and so it is possible to write a scenario
in which a player picks up an Object (a tent, say), carries
it around, and later enters it.
All Objects are represented by (unique) sixteen-bit
integers. This number is known as the "Object ID" of the
Object. Objects are (essentially) record structures with
the following elements:
Location The Object ID of the Object which contains
this Object.
Contents The Object ID of the first Object which is
contained in this Object, or zero if there is
no such Object.
Link The Object ID of the next Object which is
located in the same place as this Object or
zero if there is no such Object.
Modifier The ID of the modifier of this Object or zero
if the Object has no modifier. For example,
the Object "blue streak" would have a modifier
ID which is the adjective "blue". Modifiers
are explained further in Section 2.9.
Properties Associated with each Object are 32 properties.
While all of the above elements are maintained
directly or indirectly by the ADL system, the
values and meanings of properties are the
responsibility of the programmer. The first
16 of these properties may only hold the value
0 or 1 (hence they are usually called
c 1987 Ross Cunniff and Tim Brengle
- 4 -
"boolean" properties). Properties 17 through
32 may hold any value between -32768 and
32767. The last three of these properties
have special meaning to ADL:
LDESC (30) This is the ID of a routine
which prints a "long" descrip-
tion of the Object. Routines
are defined in Chapter 6.
SDESC (31) This is the ID of a routine
which prints a "short" descrip-
tion of the Object.
ACTION (32) This is the ID of a routine
which is called under the cir-
cumstances detailed in Chapter
4.
All Objects in ADL are stored in a tree. The root node
of the tree is predeclared and is named ".ALL". Its Object
ID is always zero. All other Objects are ultimately located
in .ALL.
Two other predeclared Objects exist. One is named
"STRING" and the other is named ".ME". .ME is not truly an
Object -- it is more like a variable which represents the
current Actor during the execution of an ADL program (more
on Actors in Section 3.1). It is illegal to use .ME outside
of the context of a routine. STRING is the Object which is
seen by the ADL program when the run-time sentence parser
encounters a string. Note that although STRING is prede-
clared by ADL, the properties of STRING must be defined by
the ADL programmer. See Chapter 9 for more information on
STRING.
2.2. Verbs
Verbs are the means whereby a player manipulates the
environment. Verbs can denote motion, investigation, mani-
pulation, and any other action the ADL programmer can ima-
gine. A Verb is represented by a sixteen-bit integer known
as the Verb ID. Like Objects, Verbs are record structures.
They have the following elements:
PREACT The ID of a routine to be called when this
Verb is typed by the player. The routine is
called before the ACTION routines of the
Objects in the sentence. See Chapter 4 for
more information.
ACTION The ID of a routine to be called when this
Verb is typed by the player. This routine is
called after the ACTION routines of the
c 1987 Ross Cunniff and Tim Brengle
- 5 -
Objects in the sentence. Again, see Chapter 4
for more information.
Verbs may also be used as modifiers to nouns. This is
to allow easy implementation of Objects like the "north
wall" or "go north" (where "north" is normally a verb of
motion).
ADL predeclares the two Verbs "TELLER" and "NOVERB"
which are returned by the parser under circumstances shown
in Chapter 9. Although TELLER and NOVERB are predeclared,
their properties must be defined by the ADL programmer.
2.3. Adjectives
Adjectives serve only one purpose: to disambiguate oth-
erwise identical nouns (such as a "red ball" and a "blue
ball"). Adjectives have no structure and exist only as
sixteen-bit Adjective IDs.
2.4. Strings
There are two forms of strings in ADL: compile-time
strings and run-time strings. Compile-time strings are
those which appear in the ADL source code for the scenario.
They are delimited by double quotes and are transformed into
positive sixteen-bit String IDs by the compiler. These
strings are free-form in that a carriage return may appear
in them at any point. This sort of carriage return is
transformed into a blank. Should the ADL programmer desire
a true carriage return, the sequence \n should be embedded
in the string at the appropriate point. Compile-time
strings may be limited to 255 characters in length in some
implementations.
Run-time strings are those which are typed by the
player and those which are generated by the built-in string
manipulation routines. Strings in player input may be del-
imited by appropriately nested single or double quotes. All
run-time strings are represented as NEGATIVE sixteen-bit
string IDs.
2.5. Numbers
There are two forms of numbers in ADL: compile-time
numbers and run-time numbers. Compile-time numbers exist in
the ADL source code for the scenario and may be any integer
in the range of -32768 to 32767 inclusive. Run-time numbers
are those which are typed by the player. Run-time numbers
are transformed into a string consisting of the ASCII
representation of their digits. A negative string ID is
then returned for eventual use by the ADL program.
c 1987 Ross Cunniff and Tim Brengle
- 6 -
2.6. Routines
Routines in ADL are represented by (what else?) sixteen
bit Routine IDs. The only operations allowed on routines
are calling them and passing them to other routines as
parameters. The syntax of ADL routines is described in
Chapter 6. The routine "START" is predeclared by ADL and
must be defined by the programmer or execution will be
prematurely terminated. The Routines "DWIMI" and "DWIMD"
are also predeclared by ADL and should be defined by the
programmer. DWIMI and DWIMD are called under circumstances
detailed in Chapter 4.
2.7. Global Variables
There are a number of global variables available for
definition and use by the ADL programmer. A global is
represented by a sixteen-bit ID and may hold any integer
value from -32768 to 32767. These values may be interpreted
as simple numbers, String IDs, Routine IDs, Object IDs, Verb
IDs, etc. depending upon how they are used. The globals
named Verb, Conj, Numd, Dobj, Prep, and Iobj are predeclared
by ADL and at run-time contain the values of the current
Verb, Conjunction, Number of Direct Objects, Direct Object,
Preposition, and Indirect Object, respectively.
The ADL programmer may declare a block of global vari-
ables for use as an array or list of things. See Chapter 5
for more information.
2.8. Local variables
Local variables differ from global variables in that
their name is limited in scope to the routine in which they
appear. They are represented by sixteen-bit IDs which may
be passed to other routines if desired. Local variables may
be implemented in one of two ways: on the stack (like local
variables on C and Pascal) in which case they are only
around for as long as the current invocation of the routine;
or they may reside in the same space as global variables
(like static locals in C or local variables in FORTRAN) in
which case they persist for the entire duration of program
execution. Consult your local ADL documentation to deter-
mine which method is used in your implementation.
2.9. Modifiers
A modifier is simply a word that modifies an ambiguous
noun to produce an Object. A modifier may be either a Verb
or an Adjective. If the modifier of an Object is a Verb, it
is represented as the NEGATIVE of the Verb ID. If it is an
Adjective it is represented by the (positive) Adjective ID.
If the modifier is zero, the Object has no modifier.
c 1987 Ross Cunniff and Tim Brengle
- 7 -
3. ADL Internal Structures
ADL maintains several internal structures to achieve
the level of interaction necessary for interesting play.
These structures are accessible only through the built-in
routines described in Chapter 7.
3.1. Actors
In a typical adventure game it seems as if the player
is moving around the dungeon taking things, smelling them,
breaking them, and so on. A better model would be that the
player is giving commands to an actor. It is the actor
which actually moves around, collects items, and otherwise
acts. It is this model which ADL follows.
An Actor is essentially an "animate" object which acts
upon commands given to it. Notice that there is nothing in
this model which prevents more than one Actor from running
around a scenario. In fact, in ADL there may be up to ten
Actors which are active at any one time.
There are two kinds of Actors: interactive and non-
interactive. The player is an example of an interactive
Actor. Commands are read directly from the keyboard and
placed in a line buffer which is then passed to the parser
and interpreter. When the line buffer is empty a new one is
read from the keyboard. Any number of Actors may be
interactive, making multiple player games a possibility.
The robot in the introductory script is an example of a
non-interactive Actor (see Appendix 2 for the source to the
scenario which produced that script). The line buffer for
the robot was initialized after the player typed the sen-
tence starting with "Tell the robot ...". The robot then
acted on this command by performing the requested actions in
parallel with the actions of the player. This means that
each Actor gets one turn for each turn that the player
experiences. A non-interactive Actor is deleted from the
list of active Actors when its line buffer is emptied.
There is a special object-like item named ".ME" used to
implement this sort of "multiprocessing". .ME represents
the Object ID of the current Actor for the purposes of mov-
ing around, taking things, etc. Anything that the player
can do can be done just as well by another Actor. This is
probably the most powerful (and most obscure) feature of
ADL.
Actors may be activated using the $actor built-in rou-
tine and deleted at any time by using the $delact routine.
c 1987 Ross Cunniff and Tim Brengle
- 8 -
3.2. Daemons
Daemons are routines which execute once for each active
Actor at the beginning of each turn. Daemons are typically
used for things like describing the player's location and
incrementing the turn counter. Daemons are activated by
using the $sdem routine and may be de-activated by using the
$ddem routine. Up to ten daemons may be active at one time.
3.3. Fuses
Fuses are routines which wait a certain amount of time,
execute, then become inactive. The list of fuses is exam-
ined each time the turn counter is incremented to see
whether any have "burned down". If so, the fuse is executed
and deleted from the list.
Fuses are typically used for things like waiting three
turns and then collapsing the room that the player was in,
or (the bane of all adventurers) running down the batteries
in a lamp. Fuses are activated by using the $sfus routine.
Up to ten fuses may be active at one time. The $dfus rou-
tine may be called if the programmer wishes to delete a fuse
before it executes (the player found more batteries!).
3.4. Prompter
Many times during the play of the game it is desired
that a player enter a line from the keyboard. Some sort of
prompting should be done in order to inform the player that
input is desired. The ADL programmer may specify a Routine
ID to do this prompting. This routine is known as the
prompter and is set by using the $prompt routine.
3.5. Run-Time Macros
Normally when the parser gets its input from the line
buffer of the current Actor, the words are what they seem to
be: simple words. ADL has a facility whereby these words
may be transformed before the parser sees them. Each word
is looked up in a table (the "macro table"). If found it is
replaced by the expansion for the macro (which may be a
string containing more than one word) and re-inserted into
the line buffer whereupon the input process continues.
One use of this facility is to "rename" objects. For
example, it may be desired that the player be able to type
something like "Name the box 'bob'. Take bob." (notice that
the second usage of bob has no quotes). This can be accom-
plished by the call ($define "bob" "box") which says to
expand "bob" to "box" whenever it is encountered in the line
buffer. The built-in routine $undef may be used to "unde-
fine" a macro if it outlives its usefulness -- for example
($undef "bob") removes "bob" from the macro table. More is
c 1987 Ross Cunniff and Tim Brengle
- 9 -
said about macros in Section 7.10 under the entries for
$define and $undef.
c 1987 Ross Cunniff and Tim Brengle
- 10 -
4. Putting It All Together
The flow of execution of the game can be described now
that the basic data types have been defined. The execution
starts with an initialization step: an ADL routine named
START is called. ADL terminates prematurely if START has
not been defined. START typically activates the principal
Actor (the player) and a looker daemon (responsible for
describing the player's surroundings), initializes the
prompter, and so on. ADL then enters a loop from which it
never returns (until program termination).
4.1. The Flow of Execution
The main loop of the game consists of a series of
phases. The built-in routine $phase will return the number
of the phase currently executing (see the flow diagram and
Section 7.12 for the number of each of the phases). At the
beginning of each turn, all active Daemons are executed for
each Actor on the Actor list -- in the REVERSE order in
which the Actors were activated. This is so newly activated
Actors don't act before the older Actors have a chance to
act. The Daemons are executed in the order in which they
were activated.
After all Daemons have executed for all Actors, a
series of phases are executed for each Actor on the Actor
list (in the reverse order of Actor activation). The loop
progresses downward in an orderly fashion unless interrupted
by a call to $exit. For information on $exit see Section
4.2. The following are the phases which are executed for
each Actor on the Actor list:
Clear Sentence The global variables Verb, Conj, Numd,
Dobj, Prep, and Iobj are set to 0. This
is done in a separate phase to facilitate
the implementation of incremental sen-
tences such as "Take. The red ball."
Input A new line buffer is prompted for and read
if the line buffer is empty and the
current Actor is interactive.
The current Actor is deleted from the
Actor list and execution continues start-
ing with the next Actor if the line buffer
is empty and the current Actor is NOT
interactive.
Parse All upper case letters in the line buffer
are transformed into lower case letters.
An attempt is then made at parsing the
line buffer into a Verb, Direct Objects, a
Preposition, and an Indirect Object. Note
c 1987 Ross Cunniff and Tim Brengle
- 11 -
that unambiguous abbreviations of words
are recognized by the parser (for example,
if the words "newt" and "newspaper" are in
the vocabulary, "new" is ambiguous but
"news" is an abbreviation of "newspaper").
An appropriate message is printed if this
does not succeed and execution continues
from the Input phase.
ADL sentences are typically of the form
"Verb DobjList Prep Iobj" "Verb Iobj
DobjList", or "Iobj, String". This is an
overly simplistic description - for a full
specification see Chapter 9.
DWIM An object may be ambiguous either through
the lack of a modifier or through the use
of a modifier without a noun (e.g. typing
"Take the ball" when there is both a "red
ball" and a "blue ball", or typing "Take
red" in the same situation).
An ADL routine named "DWIMI" is used if
the Indirect Object is ambiguous. DWIMI
is called once for each Object that could
possibly be the one meant by the player.
If EXACTLY one of these calls returns a
non-zero value then the corresponding
Object becomes the Indirect Object. How-
ever, if DWIMI never returns a non-zero
value or if it returns a non-zero value
more than once, the player is told to be
more specific and execution continues
starting with the Clear Sentence phase
above.
An ADL routine named "DWIMD" is used if
any of the Direct Objects are ambiguous.
DWIMD is called for the Objects in ques-
tion just like DWIMI.
Execution The following phases are executed for
every Direct Object in the Direct Object
list. They are executed exactly once if
there are no Direct Objects. This loop is
the heart of the ADL system and is where
the player's commands are actually carried
out.
Actor ACTION The ACTION routine of
the current Actor is
executed. It typically
checks the sentence and
possibly modifies it.
c 1987 Ross Cunniff and Tim Brengle
- 12 -
This allows the handling
of cases like "Take the
beer then drink it"
(where "it" needs to be
massaged to mean "beer")
and "Go north. Again."
(where "Again" needs to
be transformed into "Go
north").
Verb PREACT The PREACT routine of
the current Verb is exe-
cuted. It typically
guards against incorrect
use of multiple Direct
Objects, or the use of
Indirect Objects or
strings where such use
doesn't make sense. It
also might check that
all objects named are
available for use.
Iobj ACTION The ACTION routine of
the current Indirect
Object is executed.
This is where some
object-specific actions
are performed. For
example, the sentence
"Put the coins in the
slot" might be handled
here if putting coins
into the slot (as
opposed to a box or a
bag) causes something
special to happen. If
the Indirect Object is a
string then the ACTION
routine of the prede-
clared ADL Object named
STRING is executed.
Dobj ACTION The ACTION routine of
the current Direct
Object is executed.
This is where most
object-specific actions
are performed. For
example, the sentence
"Rub the lamp" might be
handled here if rubbing
the lamp is different
than rubbing any other
c 1987 Ross Cunniff and Tim Brengle
- 13 -
Object. The ACTION rou-
tine of the predeclared
ADL Object STRING is
executed if the Direct
Object is a string.
Verb ACTION The ACTION routine of
the current Verb is exe-
cuted. This is where
general default actions
are usually handled.
For example, the sen-
tence "Rub the floor"
might result in the mes-
sage "Rubbing that
object is not useful."
Room ACTION The ACTION routine of the current Actor's
location is executed once the above loop
has examined all of the Direct Objects.
This routine is typically a "transition"
routine -- that is, it might check whether
the current verb is "north" and move the
current actor to the appropriate location
(it might check other directions as
well!).
4.2. $exit
It is possible to change the normal flow of execution
by means of the $exit built-in routine. The programmer may
use ($exit 0) to halt execution of the current phase and
move on to the next phase. At any time, ($exit 1) may be
used to halt the execution of the current phase and skip to
the next Actor. Inside the Direct Object loop, ($exit 2)
may be used to skip the rest of the Object and Verb ACTIONs
and go on to the next Direct Object in the list. At any
time after the parsing phase, ($exit 3) will return the flow
of control to the Parsing phase without clearing the sen-
tence. This allows for incremental entry of sentences; for
example "The big door. Unlock. With the key".
c 1987 Ross Cunniff and Tim Brengle
- 14 -
The following is a diagram of the flow of execution:
START [0]
|
v
+--------------------------------->o
| |
| v
| Daemons [1]
| |
| v
| Get Actor <----------------------+
| | |
| v |
| +------------------> Clear Sentence |
| | | |
| | v |
| | ($exit 3)====> Get Input? --n---> Delete Actor |
| | | y | |
| | v | |
| o<---------------------- Parse? | |
| ^ | | |
| | v | |
| o<-------------fail----- DWIMI | |
| ^ | | |
| | v | |
| +--------------fail----- DWIMD | |
| | | |
| v | |
| Get Dobj <-------+ | |
| | | | |
| v | | |
| Actor ACTION [2] | | |
| Verb PREACT [3] | | |
| Iobj ACTION [4] | | |
| Dobj ACTION [5] | | |
| Verb ACTION [6] | | |
| | | | |
| v | | |
| ($exit 2)===> More Dobjs? -y----+ | |
| | n | |
| v | |
| Room ACTION [7] | |
| | | |
| v | |
| ($exit 1)=========>o<-------------------+ |
| | |
| v |
+--------------------------n- More Actors? -y-------------------+
c 1987 Ross Cunniff and Tim Brengle
- 15 -
5. ADL Programs
This chapter describes the format of ADL programs. An
ADL program consists of a list of one or more of the follow-
ing statements. Comments in ADL programs are delimited by {
and }. Since case is significant in ADL, tokens which are
identical except for differing case are different (for exam-
ple, "noun" is not the same as "NOUN").
Note: for a full BNF specification of ADL programs, see
Chapter 8.
INCLUDE "filename";
Input to the ADL compiler is read from filename
until the end of file and compilation then resumes
from the current file. A file included in compila-
tion by means of an INCLUDE statement may INCLUDE
other files.
Example:
INCLUDE "standard.adl";
MESSAGE "message";
The string message is printed on the console at com-
pile time. This is used to remind the programmer of
things which should be initialized or to simply
reassure the programmer that the compiler is indeed
reading the file.
Example:
MESSAGE "Whew! We're halfway through the file!\n";
VAR name, name, ... ;
This declares each name to be a new global variable.
The contents of global variables are initialized to
zero. Each name must not have been previously
declared. Each name may be followed by a size
specifier, in which case that number of words is
allocated. As ADL routines have no specific facili-
ties for handling arrays, it is the responsibility
of the ADL programmer to add the desired offset to
the base of the array in order to access an element
of the array For example, ($setg ($plus Array 10) 5)
is similar to Array[ 10 ] = 5 in C.
Example:
VAR
Score,
c 1987 Ross Cunniff and Tim Brengle
- 16 -
Dark,
ObjList[ 10 ],
MyLoc;
LOCAL name, name, ... ;
This statement is only legal inside routine defini-
tions. It declares each name as a new Local Vari-
able. Each name may or may not already have been
declared. If a name is the same as the name of
something declared outside the routine, that thing
cannot be directly referenced by the routine. The
name of a local variable is only visible to the rou-
tine in which it is defined. Local variables may be
arrays just as global variables may. Note that a
routine may have a maximum of 32 words of local
variables. Arrays of local variables use up that
space rather quickly, so they should be used with
care. See the next chapter for an example using
local variables.
VERB name, name, ... ;
This statement declares each name to be a new Verb.
The PREACT and ACTION routines of Verbs are initial-
ized to zero. Each name must not have been previ-
ously declared.
Example:
VERB take, drop, open, close;
ADJEC name, name, ... ;
This statement declares each name to be a new Adjec-
tive. Again, each name must not have been previ-
ously declared.
Example:
ADJEC red, green, blue;
NOUN ndecl, ndecl, ... ;
This statement declares Objects. Ndecl may take the
form obj or obj ( container ). The first form
declares a new Object located in the object .ALL.
The second form declares a new Object located in
container. Each obj may be one of: an undeclared
identifier, a modifier followed by an undeclared
identifier, or a modifier followed by a previously
declared noun. If obj is just an undeclared iden-
tifier, the identifer is declared to be a noun and a
new Object is created with that noun ID and with a
c 1987 Ross Cunniff and Tim Brengle
- 17 -
modifier of 0. If obj is a modifier followed by an
undeclared identifier, the identifier is declared to
be a noun and a new Object is created with that noun
ID and with the modifier set to the one specified.
If obj is a modifier followed by a previously
declared noun, a new Object is created with the
specified noun ID and the specified modifier. Note
that the declaration "NOUN foo, blue foo;" is ille-
gal since it would be too easy to create situations
where the player is unable to disambiguate the
Objects.
Example:
NOUN room1;
NOUN table( room1 ), chair( room1 ), red ball( room1 );
ROUTINE name, name, ... ;
This statement declares each name to be a new rou-
tine. Note that this does not associate a routine
with the Routine ID -- it just declares the routine.
This is useful for daisy-chaining routines (i.e.
routine A calls routine B, which calls routine A)
since everything must be declared before it is used.
Each name must not have been previously declared.
Example:
ROUTINE Looker, Prompter, Quitter;
ARTICLE name, name, ... ;
This statement declares each name to be a new Arti-
cle. Each name must not have been previously
declared.
Example:
ARTICLE the, a, an;
PREP name, name, ... ;
This statement declares each name to be a new Prepo-
sition. Each name must not have been previously
declared.
Example:
PREP in, into, on, above ;
obj (const) = expr ;
This statement assigns property const of obj to be
c 1987 Ross Cunniff and Tim Brengle
- 18 -
expr. Const must be a number or the name of a con-
stant (see below). Expr may be a string, a number,
a routine, another noun, or just about anything else
which yields a sixteen bit ID. Obj must be previ-
ously declared. A warning may be produced if this
particular property is reassigned later in the pro-
gram.
Example:
room1( LDESC ) =
($say "You are in a huge room.\n")
;
chair( WEIGH ) = 450 ;
table( MESSAGE ) = "This space for rent\n" ;
verb (const) = routine ;
This statement assigns property const of verb to be
routine. Const must be either PREACT or ACTION, and
verb must have been previously declared. A warning
may be produced if this particular property is reas-
signed later in the program.
Example:
take( ACTION ) = ($say "You can't take that object.\n");
drop( PREACT ) = (CheckAvail);
name = expr;
This statement declares that name is equivalent to
expr. Name must not have been previously declared
and expr may be an object, a string, a routine, a
number, or just about anything else that yields a
sixteen-bit value.
Example:
MagicWord = "AbraCadabra"; { string ID }
VISIT = 3; { constant }
Silly = ($say "That's silly!\n"); { routine ID }
toolbox = tool box; { object ID }
(global) = expr;
This statement initializes global variable global to
have the value expr. Global must have been previ-
ously declared and expr is the same as expr above.
Example:
( MyLoc ) = -1;
( Score ) = 10;
c 1987 Ross Cunniff and Tim Brengle
- 19 -
(global + const) = expr;
This statement initializes the const'th slot in the
global array global to have the value expr.
Example:
VAR foo[ 10 ];
( foo ) = 3; { Sets foo[0] to 3 }
( foo + 5 ) = 6; { Sets foo[5] to 6 }
prep1 obj prep2 = prep3;
This statement declares that if the three-word
sequence prep1 obj prep2 is encountered during run-
time parsing in the proper position for a preposi-
tion, it is to be replaced by prep3. Obj may be a
modifier-noun pair and prep1, prep2, and prep3 must
have been previously declared.
Example:
PREP
in, of, before;
NOUN
front;
in front of = before;
verb1 prep = verb2;
This statement declares that if the two-word
sequence verb1 prep is encountered during run-time
parsing in the proper position for a verb, it is to
be replaced by verb2. Verb1, verb2, and prep must
have been previously declared.
Example:
VERB
put, take, turn, wear, remove, light, douse;
PREP
on, off;
put on = wear;
take off = remove;
turn on = light;
turn off = douse;
c 1987 Ross Cunniff and Tim Brengle
- 20 -
6. Routines
This chapter describes the syntax of ADL routines. An
ADL routine consists of an optional LOCAL declaration fol-
lowed by a sequence of one or more expressions. An expres-
sion is one of the following:
Routine call A routine call in ADL takes the form (rout
arglist). Rout is either the name of a
built-in routine, the name of a user routine,
or an expression which evaluates to a Routine
ID. Arglist is a list of zero or more args
each of which is one of:
An expression
A simple expression
A simple expression is one of a
string, a number, or a name
which was declared as in Chapter
5.
@global This is interpreted to mean "the
contents (or value) of global".
%number This is interpreted to mean "the
numberth argument to this func-
tion". Note that %0 is the
number of arguments passed to
this function.
[ modif noun ]This construct must be used if
the programmer wants to use the
value of an Object which has a
modifier.
The value of the expression is the result of
executing rout with arguments arglist.
Conditional A conditional expression takes the form
( IF arg1 THEN expression ...
ELSEIF arg2 THEN expression ...
...
ELSE expression ... )
This statement evaluates arg1 and if the
result is non-zero the expressions following
THEN are executed. If the result of the
evaluation of arg is zero then the expressions
following THEN are skipped until one of ELSE,
ELSEIF or the end of the conditional are
found. If ELSEIF was found the corresponding
arg is evaluated and execution proceeds as for
IF. If none of the ELSEIFs evaluate to a
c 1987 Ross Cunniff and Tim Brengle
- 21 -
non-zero value then the ELSE expressions are
executed. The ELSEIFs and the ELSE are
optional. The conditional expression returns
the value of the last expression executed or
zero of no expressions were executed.
Loop A loop takes the form ( WHILE arg DO expres-
sion ... ). If arg evaluates to a non-zero
value then the expressions are evaluated.
This process repeats until arg evaluates to
zero. This statement always returns zero.
Example On the following page is a sample ADL routine
which demonstrates each of the above con-
structs and is almost useful as well See
Chapter 7 for the definitions of the built-in
routines called.
c 1987 Ross Cunniff and Tim Brengle
- 22 -
{ A sample looking daemon }
Look =
LOCAL obj;
($incturn) { Increment the turn counter }
(IF ($prop ($loc .ME) VISIT) THEN
{ I've been here before - print a short description }
( ($sdesc ($loc .ME)) )
ELSEIF ($ne ($cont ($loc .ME)) .ME) THEN
{ There are other objects here }
( ($ldesc ($loc .ME)) )
($say "You can see:\n")
($setg obj ($cont ($loc .ME)))
(WHILE @obj DO
{ Describe each object in the room }
( ($sdesc @obj) )
($setg obj ($link @obj))
)
ELSE
{ I've never been here }
( ($ldesc ($loc .ME)) )
($say "There is nothing else in the room.\n")
)
($setp ($loc .ME) VISIT TRUE)
;
c 1987 Ross Cunniff and Tim Brengle
- 23 -
7. ADL Built-in Routines
The following is the complete list of ADL built-in rou-
tines. They are organized into groups of related routines.
A description of each routine is provided with at least one
example to clarify its usage. The following groupings of
built-in routines are detailed in this chapter:
7.1 Object Routines
7.2 Verb Routines
7.3 Arithmetic Routines
7.4 Boolean Routines
7.5 Global Value Routines
7.6 Transition Routines
7.7 String Manipulation Routines
7.8 Name Routines
7.9 Conversion Routines
7.10 Internal Structure Manipulation Routines
7.11 Special Routines
7.12 Miscellaneous Routines
c 1987 Ross Cunniff and Tim Brengle
- 24 -
7.1. Object Routines
These routines operate primarily on Objects. They move
Objects around, find Object properties, and set Object pro-
perties.
$loc ( $loc obj ) -> The location of obj.
Example:
(IF ($eq ($loc .ME) volcano) THEN
($say "You are fried to a crisp.\n")
)
$cont ( $cont obj ) -> The first object which is contained
in obj.
Example:
(IF ($eq ($cont .ME) 0) THEN
($say "You are empty-handed.\n")
)
$link ( $link obj ) -> The next object contained in the
same location as obj.
Example:
($setg obj ($cont .ME))
(WHILE @obj DO
($say ($name @obj) "\n")
($setg obj ($link @obj))
)
$ldesc ( $ldesc obj ) -> The long description of obj. This
is equivalent to ($prop obj LDESC). Since this is a
Routine ID, it is typically used as the callee in a
routine call.
Example:
($setg obj ($loc .ME))
( ($ldesc @obj) ) { Call LDESC of ($loc .ME) }
$sdesc ( $sdesc obj ) -> The short description of obj.
This is equivalent to ($prop obj SDESC). Since this
is a Routine ID, it is typically used as the callee
in a routine call.
Example:
c 1987 Ross Cunniff and Tim Brengle
- 25 -
($setg obj ($loc .ME))
( ($sdesc @obj) ) { Call SDESC of ($loc .ME) }
$action ( $action obj ) -> The ACTION routine of obj. This
is equivalent to ($prop obj ACTION). Since this is
a Routine ID, it is typically used as the callee in
a routine call.
Example:
( ($action .ME) ) { Call ACTION of .ME }
c 1987 Ross Cunniff and Tim Brengle
- 26 -
$modif ( $modif obj ) -> The modifier of obj. This is zero
if there is no modifier, negative if the modifier is
a Verb, and positive if the modifier is an Adjec-
tive.
Example:
(IF ($eq ($modif [ blue ball ] ) blue) THEN
($say "$modif works!\n")
)
(IF ($eq ($modif [ north wall ] ) ($minus 0 north)) THEN
($say "$modif still works!\n")
)
(IF ($eq ($modif room1) 0) THEN
($say "$modif comes through one more time!\n")
)
$prop ( $prop obj num ) -> The numth property of obj.
Example:
($setg obj ($loc .ME))
(IF ($prop @obj VISIT) THEN
($say "I've been here before!\n")
)
$setp ( $setp obj num val ) -> No return value. Sets the
numth property of obj to val.
Example:
($setg obj ($loc .ME))
($setp @obj VISIT TRUE)
$move ( $move obj loc ) -> No return value. Moves obj to
loc. WARNING: Do not attempt to violate the tree
structure of objects (e.g. ($move .ALL foobar)) or
horrible and unpredictable things will happen.
Example:
(IF ($eq @Verb north) THEN
($move .ME room2)
)
c 1987 Ross Cunniff and Tim Brengle
- 27 -
7.2. Verb Routines
These two routines operate on Verbs. They are provided
for scenarios in which the properties of Verbs may change.
$vset ( $vset verb prop val ) -> No return value. The pro-
perty prop of verb is set to val. Prop must be
either PREACT or ACTION.
Example:
($vset @Verb PREACT Silly)
$vprop ( $vprop verb prop ) -> The value of property prop
of verb. Prop must be either PREACT or ACTION.
Example:
{ Call Verb's PREACT }
( ($vprop @Verb PREACT) )
c 1987 Ross Cunniff and Tim Brengle
- 28 -
7.3. Arithmetic Routines
These routines operate on arbitrary sixteen-bit
numbers, and return sixteen-bit values. Note that the
numbers may actually be Object IDs, global variable IDs, or
any of the sixteen bit IDs used by ADL.
$plus ( $plus num1 num2 ) -> Returns num1 + num2.
Example:
($setg Score ($plus @Score 50))
$minus ( $minus num1 num2 ) -> Returns num1 - num2.
Example:
($setg LivesLeft ($minus @LivesLeft 1))
$times ( $times num1 num2 ) -> Returns num1 * num2.
Example:
($setg TimeLeft ($times @NumBattery 10))
$div ( $div num1 num2 ) -> Returns num1 / num2.
Example:
($setg Rating ($div @Score 100))
$mod ( $mod num1 num2 ) -> Returns the remainder which
results when num1 is divided by num2 according to
normal integer division.
Example:
{ Make sure XPos is from 0 to 9 }
($setg XPos ($mod @Xpos 10))
$rand ( $rand num ) -> Returns a random number from 1 to
num inclusive.
Example:
{ Move the player to a random room from room1 to room10 }
($setg Num ($rand 10))
($move .ME ($plus room1 ($minus @Num 1)))
c 1987 Ross Cunniff and Tim Brengle
- 29 -
7.4. Boolean Routines
These routines are typically used in conditionals and
loops. However, traditional bit-masking may be done with
$and and $or.
$and ( $and a b c ... ) -> Returns the bitwise AND of the
vector a b c .... Note that since this is the bit-
wise AND, care must be taken in conditions since
ANDing two non-zero values does not necessarily
return a non-zero value.
Example:
($and 2 4) is 0 (0b0001 AND 0b0010 = 0b0000)
($and 3 7) is 3 (0b0011 AND 0b0111 = 0b0011)
($and 1 1) is 1 (0b0001 AND 0b0001 = 0b0001)
$or ( $or a b c ... ) -> Returns the bitwise OR of the
vector a b c ....
Example:
($or 0 0) is 0 (0b0000 OR 0b0000 = 0b0000)
($or 1 2) is 3 (0b0001 OR 0b0010 = 0b0011)
($or 1 1) is 1 (0b0001 OR 0b0001 = 0b0001)
$not ( $not num ) -> Returns zero if num is non-zero and
one if num is zero. Note that this is BOOLEAN NOT
and not BITWISE NOT. BITWISE NOT could be coded as
($minus ($minus 0 %1) 1) for a two's complement
machine.
Example:
($not 0) is 1
($not 1) is 0
($not 5) is 0
$yorn ( $yorn ) -> Waits for the player to type a line of
input, returns one if this line begins with the
letter 'Y' or 'y', and returns zero otherwise. Note
that no prompt is automatically made for this input.
Example:
($say "Are you sure you want to quit? ")
(IF ($yorn) THEN
($say "OK. Goodbye!\n")
($spec 3)
ELSE
c 1987 Ross Cunniff and Tim Brengle
- 30 -
($say "Whew! That was a close one!\n")
)
$pct ( $pct num ) -> Returns one num percent of the time
and zero the rest of the time. This is equivalent
to ($ge num ($rand 100)).
Example:
(IF ($pct 30) THEN
($say "The troll swings at you, and hits!\n")
ELSE
($say "The troll's axe misses you by a hair!\n")
)
$eq ( $eq num1 num2 ) -> Returns one if num1 is equal to
num2 and zero otherwise.
Example:
($setg loc ($loc .ME))
(IF ($eq @loc room1) THEN
($say "You are in room 1.\n")
)
$ne ( $ne num1 num2 ) -> Returns one if num1 is not
equal to num2 and zero otherwise.
Example:
($setg loc ($loc .ME))
(IF ($ne @LastLoc @loc) THEN
($say "You've moved since I last checked!\n")
)
$lt ( $lt num1 num2 ) -> Returns one if num1 is less
than num2 and zero otherwise.
Example:
(IF ($lt @Score 100) THEN
($say "You are a novice adventurer\n")
)
$gt ( $gt num1 num2 ) -> Returns one if num1 is greater
than num2 and zero otherwise.
Example:
c 1987 Ross Cunniff and Tim Brengle
- 31 -
(IF ($gt @Score 1000) THEN
($say "You are a super master grand ")
($say "champion mongo adventurer!!!\n")
)
$le ( $le num1 num2 ) -> Returns one if num1 is less
than or equal to num2 and zero otherwise.
Example:
(IF ($le @Score 1000) THEN
($say "You are a pretty good adventurer.\n")
)
$ge ( $ge num1 num2 ) -> Returns one if num1 is greater
than or equal to num2 and zero otherwise.
Example:
(IF ($ge @Weight 200) THEN
($say "The ice breaks under your weight!\n")
)
c 1987 Ross Cunniff and Tim Brengle
- 32 -
7.5. Global Value Routines
$setg ( $setg which val ) -> Returns val. Sets the con-
tents of (or the value of) variable which to be val.
$global ( $global which ) -> Returns the contents of (or the
value of) variable which. Equivalent to @which,
with the exception that $global allows arithmetic
expressions.
Example:
Given:
VAR var[3];
(var + 0) = 10;
(var + 1) = 20;
(var + 2) = 30;
The statement
($global ($plus var 2))
would return 30.
$verb ( $verb ) -> Returns the current Verb. Equivalent
to @Verb.
Example:
(IF ($eq ($verb) take) THEN
($say "You can't take that!!\n")
)
$dobj ( $dobj ) -> Returns the current direct object.
Equivalent to @Dobj.
Example:
(IF ($eq ($dobj) ball) THEN
($say "Dobj = ball\n")
)
$iobj ( $iobj ) -> Returns the current indirect object.
Equivalent to @Iobj.
Example:
(IF ($eq ($iobj) basket) THEN
($say "Iobj = basket\n")
)
c 1987 Ross Cunniff and Tim Brengle
- 33 -
$prep ( $prep ) -> Returns the current Preposition.
Equivalent to @Prep.
Example:
(IF ($eq ($prep) into) THEN
($say "Prep = into\n")
)
$conj ( $conj ) -> Returns the current conjunction.
Equivalent to @Conj.
Example:
(IF ($eq ($conj) 1) THEN
($say "The conjunction was 'but'\n")
ELSE
($say "The conjunction was 'and' or ','\n")
)
$numd ( $numd ) -> Returns the length of the current
direct object list. Equivalent to @Numd.
Example:
(IF ($gt ($numd) 1) THEN
($say "You may not use multiple direct objects!\n")
)
c 1987 Ross Cunniff and Tim Brengle
- 34 -
7.6. Transition Routines
ADL has an internal structure known as the Transition
Vector. This structure is a list of ten verb IDs and is set
and used by the following routines. These routines are typ-
ically used in the ACTION routines of rooms in scenarios in
order to move the player around.
$setv ( $setv verb1 verb2 verb3 ... verb10 ) -> No return
value. Initializes the Transition Vector to the
list of verbs verb1 verb2 verb3 ... verb10.
Example:
($setv north south east west ne se nw sw up down)
$hit ( $hit obj loc1 loc2 loc3 ... loc10 ) -> No return
value. Scans the Transition Vector for a match with
the current Verb. If found, obj is moved to the
corresponding loc. Nothing happens if no match is
found. An attempt to move an object to location 0
(.ALL) is ignored.
Example:
room1(ACTION) =
($hit .ME room2 room3 room4 0 0 0 0 0 0 0)
;
$miss ( $miss rout1 rout2 rout3 ... rout10 ) -> No return
value. Scans the Transition Vector for a match with
the current Verb. If found, the corresponding rout
is called. Nothing happens if no match is found.
An attempt to call routine 0 does nothing.
Example:
cg = ($say "You can't go that way.\n")
room2(ACTION) =
($miss 0 0 0 cg cg cg cg cg cg cg)
;
c 1987 Ross Cunniff and Tim Brengle
- 35 -
7.7. String Manipulation Routines
There are basically three types of strings which an ADL
program uses. The first type of string is the compile-time
string (a string which was present in the ADL source file of
the scenario). All compile-time strings have a positive
string ID and exist for the duration of program execution.
The second type of string is the "volatile" run-time
string. Examples of this type of string include strings
typed by the player and strings produced by the builtin rou-
tines $subs, $cat, $read, $name, $vname, $mname, $pname,
$num, and $chr (see also Sections 7.8 and 7.9). Volatile
strings have negative string IDs and are "flushed" at the
beginning of each turn (just before the Daemon phase).
The third type of string is the "non-volatile" run-time
string. These strings also have negative string IDs but
they are never "flushed". These strings are produced by the
$savestr routine. Note that there is no easy way to distin-
guish volatile and non-volatile run-time strings.
In the context of the $subs and $pos routines, strings
are indexed starting at zero (the first character of the
string). The following routines operate on all types of
strings:
$eqst ( $eqst str1 str2 ) -> Returns one if str1 has the
same contents as str2 and zero otherwise. Note that
this is NOT the same as ($eq str1 str2), since the
$eq only compares the string IDs of the strings.
Example:
The program:
($setg str1 "hello")
($setg str2 ($cat "he" "llo"))
(IF ($eqst @str1 @str2) THEN
($say "String 1 == string 2\n")
)
(IF ($ne @str1 @str2) THEN
($say "String ID 1 != string ID 2\n")
)
will produce the output:
String 1 == string 2
String ID 1 != string ID 2
$subs ( $subs str start len ) -> Returns a volatile copy
of the substring of str starting at start and going
for len characters. If len is 0, the suffix of str
starting at start is returned.
c 1987 Ross Cunniff and Tim Brengle
- 36 -
Example:
The program:
($setg str "Hello world")
($say ($subs @str 0 5) "\n")
($say ($subs @str 6 0) "\n")
will produce the output:
Hello
world
$leng ( $leng str ) -> Returns the length of str.
Example:
($leng "Hello") is 5
($leng "") is 0
$cat ( $cat str1 str2 ) -> Returns a volatile string
which is the result of concatenating str1 and str2.
Example:
($cat "hello " "world") returns "hello world"
$pos ( $pos str1 str2 ) -> Returns the position of str1
in str2. If no occurrence of str1 is found in str2,
-1 is returned.
Example:
($pos "hello" "hello world") is 0
($pos "Foobar" "bletch") is -1
($pos "testing" "This is a test") is -1
($pos "is" "This is a test") is 2
$read ( $read ) -> Returns a volatile string which is read
from the player's keyboard. Note that no prompt is
automatically generated.
Example:
($say "What is your name? ")
($setg MyName ($read))
($say "Hello, " @MyName ", welcome to ADL!\n")
$savestr( $savestr str ) -> Returns a non-volatile copy of
str. Note that str may be any string -- compile-
time, volatile, or non-volatile.
c 1987 Ross Cunniff and Tim Brengle
- 37 -
Example:
($setg MyName ($savestr @MyName))
c 1987 Ross Cunniff and Tim Brengle
- 38 -
7.8. Name Routines
The following routines all return volatile strings
which contain the requested name.
$name ( $name obj ) -> Returns a volatile string contain-
ing the (possibly multiple-word) name of obj.
Example:
($say "You see no " ($name @Dobj) " here!\n")
$vname ( $vname verb ) -> Returns a volatile string con-
taining the name of verb.
Example:
($say "No multiple objects with " ($vname @Verb) "!\n")
$mname ( $mname modif ) -> Returns a volatile string con-
taining: the name of modifier modif (if modif is
greater than zero), the name of verb -modif (if
modif is less than zero), or the null string (if
modif is zero).
Example:
($say "The modifier of blue ball is " ($mname blue) "\n")
$pname ( $pname prep ) -> Returns a volatile string con-
taining the name of Preposition prep.
Example:
($say "The sentence is:\n")
($say ($vname @Verb) " "
($name @Dobj) " "
($pname @Prep) " "
($name @Iobj)
)
c 1987 Ross Cunniff and Tim Brengle
- 39 -
7.9. Conversion Routines
The following routines perform conversions between
strings and numbers.
$str ( $str num ) -> Returns a volatile string which con-
tains the ASCII representation of num.
Example:
($str 3) is the string "3"
$num ( $num str ) -> Returns the numeric value of str.
Example:
($num "234") is the number 234
$ord ( $ord str ) -> Returns the ASCII code of the first
character in str.
Example:
($ord "ABC") is 65
$chr ( $chr num ) -> Returns a volatile string which con-
tains exactly one character, whose ASCII code is
num.
Example:
($chr 97) is the string "a".
c 1987 Ross Cunniff and Tim Brengle
- 40 -
7.10. Internal Structure Manipulation Routines
The following routines are the means whereby the ADL
programmer may modify the Internal Structures described in
Chapter 3. See also Chapter 4 for the use of some of these
routines.
$sdem ( $sdem rout ) -> No return value. Activates rout
as a daemon.
Example:
($sdem Looker)
($sdem Follower)
$ddem ( $ddem rout ) -> No return value. De-activates
rout as a daemon. No action is taken if rout is not
an active daemon.
Example:
($ddem Follower)
$sfus ( $sfus actor rout count ) -> No return value.
Activates rout as a fuse associated with actor to be
executed in count turns.
Example:
($sfus .ME LampDie 300)
$dfus ( $dfus actor rout ) -> No return value. De-
activates rout as a fuse associated with actor. No
action is taken if rout is not an active fuse.
Example:
(IF @BatteryFound THEN
($dfus .ME LampDie)
)
$incturn( $incturn [ nturns ] ) -> No return value. Incre-
ments the turn counter by nturns (or 1 if nturns is
not given) and activates any fuses associated with
the current actor that have "burned down". The
"burned down" fuses are then de-activated. The ADL
programmer to "halt time" by refraining from incre-
menting the turn counter. Usually, ($incturn) is
only called when the daemons are executing for the
primary actor. For other actors, ($incturn 0) is
c 1987 Ross Cunniff and Tim Brengle
- 41 -
used to see whether the fuses associated with the
current actor have burned down, without incrementing
the turn counter.
Example:
sleep(ACTION) = ($incturn 300) ;
$turns ( $turns ) -> Returns the current value of the turn
counter.
Example:
(IF ($eq @Verb north) THEN
(IF ($gt ($turns) 230) THEN
($move .ME room3)
ELSE
($move .ME room5)
)
)
$prompt ( $prompt rout ) -> No return value. Sets the
prompter to be rout.
Example:
($prompt Prompter)
$actor ( $actor obj str flag ) -> No return value.
Activates obj as a new Actor with the line buffer
initialized to str. If flag is non-zero then the
new Actor will be interactive. If flag is zero then
the new Actor will be non-interactive. If str is
zero then the line buffer will be initialized to the
empty string.
Example:
($actor Myself NULL TRUE)
($setg s "Go east then south. Push button. Go north")
($actor robot @s FALSE)
$delact ( $delact obj ) -> No return value. Deletes the
Actor associated with obj from the Actor list. No
action is performed if obj is not an active Actor.
Example:
(IF ($prop robot BROKEN) THEN
($delact robot)
)
c 1987 Ross Cunniff and Tim Brengle
- 42 -
$define ( $define str1 str2 ) -> No return value. Informs
the parser that upon input from an Actor, the string
str1 is to be replaced with the contents of str2.
This process continues until an infinite loop is
detected or until a word is found for which there is
no corresponding expansion. Str1 must contain no
spaces. Str2 may contain several words separated by
spaces. Note that in the case of multiple defini-
tions (such as ($define "a" "b") followed by
($define "a" "c")), the macro table should be viewed
as a stack with $define pushing macro definitions on
the stack and $undef popping definitions.
Example:
(IF ($eq @MyDir 1) THEN
($define "left" "north")
($define "right" "south")
ELSE
($define "left" "south")
($define "right" "north")
)
$undef ( $undef str ) -> No return value. This routine
removes str and its expansion from the macro table.
No action is performed if str is not an active
macro.
Example:
($undef "left")
($undef "right")
c 1987 Ross Cunniff and Tim Brengle
- 43 -
7.11. Special Routines
$spec ( $spec code arg1 arg2 ... argN ) -> No return
value. Performs a special, system-dependent opera-
tion. Note that not all operations exist in all
implementations. Consult your local ADL documenta-
tion for information.
+------+---------------------------------------+
| code | function |
+------+---------------------------------------+
| 1 | Toggle the instruction trace flag |
| 2 | Restart this game |
| 3 | Terminate execution of this game |
| 4 | Save this game in file arg1 |
| 5 | Restore this game from file arg1 |
| 6 | Execute the system program named arg1 |
| 7 | Preserve unknown words in file arg1 |
| 8 | Write a script to file arg1 |
| 9 | Print a header line on the screen |
| 10 | Set the right margin |
+------+---------------------------------------+
Function 1
Toggles the instruction trace flag. If this
flag is set, an instruction trace and stack
dump are printed for every ADL instruction exe-
cuted (a very messy but informative process).
Function 2
Re-initializes all ADL structures and vari-
ables, re-executes START, and generally starts
the game over from the beginning.
Function 3
Terminates the game immediately, no questions
asked.
Function 4
Saves a "core image" of the ADL structures and
variables sufficient to restore the game to the
same position later.
Function 5
Reads a "core image" which was created by a
previous invocation of Function 4, thus restor-
ing the game to its previous state.
Function 6
Runs the program arg1 with arguments arg2
through argN. All arguments must be strings,
except the last argument which must be 0.
c 1987 Ross Cunniff and Tim Brengle
- 44 -
Function 7
Starts recording those words from the player's
input which are unrecognized by the run-time
parser. The words are appended to the file
named by arg1. This recording is stopped if
arg1 is 0.
Function 8
Starts recording a "script" of all input and
output produced during the subsequent execution
of the game. The script is written into the
file named by arg1. Stops recording if arg1 is
0.
Function 9
Prints a line of the form "Room Name
Score: NN Moves: NN" at the top of the
screen. It is assumed that arg1 is the name of
the room, arg2 is the current score, and arg3
is the number of turns that have passed.
Function 10
Sets the right margin to arg1. This function
is provided for the use of those games whose
messages would look better on narrower (or
wider) screens than the default of 80 columns.
Examples:
VERB debug;
debug(ACTION) = ($spec 1);
VERB restart;
restart(ACTION) = ($spec 2);
VERB quit;
quit(ACTION) = ($spec 3);
VERB save;
save(ACTION) =
LOCAL name;
($say "Save to what filename? ")
($setg name ($read))
(IF ($leng @name) THEN
($spec 4 @name)
)
;
VERB restore;
restore(ACTION) =
LOCAL name;
($say "Restore from what filename? ")
($setg name ($read))
(IF ($leng @name) THEN
($spec 5 @name)
c 1987 Ross Cunniff and Tim Brengle
- 45 -
)
;
VERB shell;
shell(ACTION) =
($spec 6 "/bin/csh")
;
VERB savewords;
savewords(ACTION) =
($spec 7 "unknown.wrds")
;
VERB script;
script(ACTION) =
LOCAL name;
($say "Script to what filename? ")
($setg name ($read))
(IF ($leng @name) THEN
($spec 8 @name)
)
;
Status = ($spec 9 ($name ($loc .ME)) @Score ($turns)) ;
START = ($spec 10 60); { It makes the text prettier }
c 1987 Ross Cunniff and Tim Brengle
- 46 -
7.12. Miscellaneous Routines
These routines are placed here for lack of a better
place to put them.
$say ( $say str1 str2 ... ) -> No return value. Prints
the messages str1 str2 ... on the screen. Note that
ADL automatically "word-wraps" strings so that they
fit within the right margin as closely as possible.
Therefore, it is not necessary for the ADL program-
mer to take great care in formatting the messages
passed to $say. If the programmer desires that the
current line be terminated, and output start on a
new line, the character sequence "\n" should be
embedded in the string. Note that each str may
actually be an expression such as ($name foo) or
($num @Score).
Example:
($say "Hi! My name is " @MyName "! How are you today?\n")
Note that MyName is assumed to contain a string ID.
$arg ( $arg num ) -> Returns the numth argument of the
current routine. It is basically the same as %num
except that in this case num may be a numeric
expression, not just a numeric constant. ($arg 0)
returns the number of arguments passed to this invo-
cation of the current routine.
Example:
{ Print all of the arguments to this routine }
($setg i 1)
(WHILE ($le @i %0) DO
($say "Arg " @i " = " ($arg @i) "\n")
)
$exit ( $exit code ) -> Doesn't return to the current rou-
tine. $exit terminates execution of the current
phase. If code is 0, control passes to the next
phase. If code is 1, control passes to the outer-
most loop. If code is 2, control passes to the top
of the Dobj loop. If code is 3, control passes to
the parser which attempts to complete a partial sen-
tence. See the diagram in Chapter 4 for a complete
definition.
Example:
take(PREACT) =
(IF ($ne ($loc @Dobj) ($loc .ME)) THEN
c 1987 Ross Cunniff and Tim Brengle
- 47 -
($say "You don't see that here!\n")
{ Skip the rest of the phases }
($exit 1)
)
;
safe(ACTION) =
(IF ($eq @Verb take) THEN
($say "You can't budge the safe.\n")
{ Go on to the rest of the Dobjs }
($exit 2)
)
;
ball(ACTION) =
(IF ($prop ball BROKEN) THEN
{ Rely on the default verb ACTION }
($exit 0)
)
($say "The ball bounces nicely.\n")
;
NOVERB(PREACT) =
($say "What do you want me to do with the "
($say ($name @Dobj) "?\n")
{ Re-parse the sentence }
($exit 3)
;
$return ( $return expr ) -> Doesn't return to the current
routine. Evaluates expr and returns the result to
the current routine's caller. Note that in the
absence of an explicit $return, the return value of
a routine is the same as the value of the last
statement executed.
Example:
Increment = ($return ($plus %1 1))
($say "Increment( 3 ) = " (Increment 3) "\n")
Increment( 3 ) = 4
$val ( $val expr ) -> Evaluates expr and returns the
result. Expr may be a routine call, a constant, a
string, or anything that yields a 16-bit value.
This routine is most useful in conditional expres-
sions.
Example:
Signum =
(IF ($lt %1 0) THEN
($val -1)
ELSEIF ($eq %1 0) THEN
c 1987 Ross Cunniff and Tim Brengle
- 48 -
($val 0)
ELSE
($val 1)
)
;
$phase ( $phase ) -> Returns the number of the phase
currently executing. This number is 0 during the
START phase, 1 during the Daemon phase, 2 during the
Actor ACTION, 3 during the Verb PREACT, 4 during the
Iobj ACTION, 5 during the Dobj ACTION, 6 during the
Verb ACTION, and 7 during the Room ACTION.
Example:
(IF ($eq ($phase) 2) THEN
($say "This is the Actor ACTION\n")
ELSEIF ($eq ($phase) 4) THEN
($say "This is the Iobj ACTION\n")
ELSEIF ($eq ($phase) 5) THEN
($say "This is the Dobj ACTION\n")
)
c 1987 Ross Cunniff and Tim Brengle
- 49 -
8. ADL Program Structure
In the following extended BNF description of ADL pro-
gram structure, terminal symbols are in BOLD UPPERCASE and
non-terminals in lowercase. Items enclosed in quotes are
literal terminals.
adlprog = stmt *
stmt = "INCLUDE" STRING ";"
= "MESSAGE" STRING ";"
= decl
= assign
decl = "VERB" ilist
= "ADJEC" ilist
= "ROUTINE" ilist
= "ARTICLE" ilist
= "PREP" ilist
= "VAR" vlist
= "NOUN" nlist
assign = ID "=" expr ";"
= nounp "(" nprop ")" "=" expr ";"
= VERB "(" vprop ")" "=" routine ";"
= "(" VAR [ "+" const ] ")" "=" expr ";"
= PREP nounp PREP "=" PREP ";"
= VERB PREP "=" VERB ";"
ilist = ID ( "," ID ) * ";"
vlist = vdec ( "," vdec ) * ";"
vdec = ID [ "[" const "]" ]
nlist = nloc ( "," nloc ) * ";"
nloc = nounp [ "(" nounp ")" ]
nounp = [ modif ] NOUN
= OBJECT
modif = VERB
= ADJEC
vprop = "PREACT"
= "ACTION"
nprop = const
= "LDESC"
= "SDESC"
= "ACTION"
c 1987 Ross Cunniff and Tim Brengle
- 50 -
const = NUMBER
= CONST_ID
expr = const
= STRING
= nounp
= routine
= modif
= ROUTINE
= PREP
= ARTICLE
= VAR
routine = [ locals ] form +
locals = "LOCAL" vlist
form = "(" ifthen elseif * [ else ] ")"
= "(" "WHILE" arg "DO" form + ")"
= "(" arg + ")"
ifthen = "IF" arg "THEN" form +
elseif = "ELSEIF" arg "THEN" form +
else = "ELSE" form +
arg = form
= "@" VAR
= "[" nounp "]"
= ".ME"
= "%"NUMBER
= const
= STRING
= NOUN
= OBJECT
= ROUTINE
= modif
= PREP
= ARTICLE
= VAR
= vprop
= nprop
c 1987 Ross Cunniff and Tim Brengle
- 51 -
9. ADL Sentence Structure
In the following extended BNF description of ADL sen-
tences, terminal symbols are in BOLD UPPERCASE and non-
terminals in lowercase. A CONJ is one of the word "and", a
comma (","), or the word "but"; a SEP is one of a period
("."), the word "then", or a newline. Comment statements
start with "--" and continue to the end of the line.
input-line = ( sentence SEP ) *
sentence = simple-sent -- Verb, Iobj, and Dobj are
-- as you would expect
= noverb-sent -- Verb = NOVERB; Iobj and Dobj
-- are as you would expect
= teller-sent -- Verb = TELLER; Iobj = object;
-- Dobj = STRING
simple-sent = verb-phrase [ dobj-list ] [ prep object ] [ prep ]
= verb-phrase object dobj-list [ prep ]
noverb-sent = [ dobj-list ] [ prep object ] [ prep ]
= object dobj-list [ prep ]
teller-sent = object "," STRING
= object "," VERB REST-OF-STRING
verb-phrase = VERB PREP *
dobj-list = object ( CONJ object ) *
object = [ ARTICLE ] modif NOUN
= [ ARTICLE ] modif
= [ ARTICLE ] NOUN
= [ ARTICLE ] OBJECT
= STRING
modif = VERB
= ADJEC
prep = PREP
= PREP PREP
= PREP object PREP
c 1987 Ross Cunniff and Tim Brengle
- 52 -
10. standard.adl
Standard.adl is a file that contains many useful
default definitions and routines. To use standard.adl, sim-
ply put 'INCLUDE "standard.adl"' before the rest of your
program.
Standard.adl defines six things: object properties,
constants, global variables, useful words, some normal verbs
and their actions, and some utility routines.
10.1. Object properties
The following object properties are defined in
standard.adl. The ADL programmer using standard.adl is
advised not to re-use these properties with different
meanings, as strange and unusual things will happen.
SEEN = 16;
OPENS = 15;
LOCKS = 14;
OPENED = 13;
LOCKED = 12;
TRANS = 11;
LIGHT = 10;
FLAME = 9;
NOTAKE = 8;
AllLink = 29;
SAVESENT = 28;
This leaves boolean properties 1 though 7 and integer
properties 17 through 28 free for the programmer's
definition and use. The above properties are used as
follows:
SEEN The standard looking daemon sets this
property of a room to TRUE whenever the
player visits the room.
OPENS This property should be set to TRUE if it
is possible to open or close the object
(a treasure chest would be an example of
this).
LOCKS This property should be set to TRUE if it
is possible to lock or unlock the object
(a door might be a good example of this).
OPENED This property is set to TRUE if the
object is already opened and FALSE if the
object is closed. This is meaningful
only if OPENS is TRUE.
LOCKED This property is set to TRUE if the
c 1987 Ross Cunniff and Tim Brengle
- 53 -
object is locked and FALSE if the object
is unlocked. This is meaningful only if
LOCKS is TRUE.
TRANS This property should be set to TRUE if
the object is transparent (a glass box or
a bottle would be a good example of
this).
LIGHT This property should be set to TRUE if
the object gives off light (in the case
of a transportable object like a flash-
light) or if the object is intrinsically
lit (like an outdoor location).
FLAME This property should be set to TRUE if
the object is on fire.
NOTAKE This property should be set to TRUE if it
is desired that "take" and "drop" ignore
the object when "take all" or "drop all"
are requested.
AllLink This property is used by the PREACT and
ACTION routines of the verbs "take" and
"drop" and should not be used by anything
else.
SAVESENT This property is used to hold the start-
ing number of a block of six global vari-
ables in which to store a sentence for
use with ActAction, below.
10.2. Constants
For convenience and readability, standard.adl defines
the following constants:
TRUE = 1;
FALSE = 0;
NULL = 0;
In addition, the following constants are defined for
use as arguments to the $spec routine:
DEBUG = 1;
RESTART = 2;
QUIT = 3;
SAVE = 4;
RESTORE = 5;
EXEC = 6;
PRESERVE = 7;
c 1987 Ross Cunniff and Tim Brengle
- 54 -
SCRIPT = 8;
HEADER = 9;
MARGIN = 10;
The following constants are defined for use as argu-
ments to the Expect routine (described in section
10.6):
NO_OBJ = 1;
ONE_OBJ = 2;
MULT_OBJ = 4;
PLAIN_OBJ = 8;
STR_OBJ = 16;
The following global variables are declared by
standard.adl for use by the ADL programmer:
Skip,
Indent,
Dark,
MyLoc,
Verbose,
Scripting,
LastVerb,
LastNumd,
LastDobj,
LastPrep,
LastIobj;
The above globals are used as follows:
Skip Skip is used in preference to ($exit 1)
or ($exit 2) inside Object ACTIONs if it
is desired that the rest of the Object
list be processed by the Verb ACTION of
"take" or "drop" (see the discussion on
TakeAct and DropAct below).
Indent Indent should be set to TRUE if object
descriptions are to be indented by two
spaces before being printed.
Dark Dark is TRUE if it is currently dark.
This variable is set by the Looker rou-
tine if there is no light in the current
location of .ME, and may also be set as
the result of some other action.
MyLoc MyLoc is the location of the player at
the outset of the previous turn. The
routine Looker checks to see whether
MyLoc is the same as the location of the
c 1987 Ross Cunniff and Tim Brengle
- 55 -
player. If so, the room description is
printed. If not, no action is performed
by Looker. MyLoc is initialized to -1 to
force the printing of a room description
at the beginning of the game.
Verbose Verbose should be set to TRUE if the
player wishes that all room descriptions
be verbose ones (i.e. long descriptions
of the room and its contents). If Ver-
bose is false and the room has been
visited previously, a short description
will be printed.
Scripting Scripting is set to TRUE by the ACTION of
the Verb "script" when output is being
scripted to a file. It is FALSE other-
wise.
LastVerb LastVerb, LastNumd, LastDobj, LastPrep,
and LastIobj contain the values present
in the sentence prior to the current sen-
tence. These values are set in the stan-
dard looking daemon. The routine
SaveSentence is provided for this pur-
pose.
10.3. Words
The following words are defined to be a standard part
of the ADL vocabulary:
PREP with, to, into, at, under, from, off, on;
in = into;
ARTICLE the, a, an;
NOUN all, it;
10.4. Verbs and their actions
Standard.adl declares the following verbs, and initial-
izes their PREACT and ACTION routines to (usually)
fairly simply-minded defaults.
n, s, e, w,
ne, se, nw, sw,
up, down,
enter, exit,
get, put, take, drop,
wear, remove,
c 1987 Ross Cunniff and Tim Brengle
- 56 -
verbose, terse,
open, close,
lock, unlock,
move, break, rub, touch,
throw, read, burn,
examine, look, inventory,
quit, restart,
save, restore, script,
turn, douse, light,
wait, again, go;
The following verbs have special semantics and redefin-
ition of their PREACT or ACTION routines should be
avoided:
NOVERB NOVERB (which is predeclared by ADL) is
the verb returned by the parser if the
player's sentence contained no verb.
Standard.adl initializes the PREACT of
NOVERB so that appropriate requests for
more information are generated.
put "Put" transforms itself into "drop" then
calls the PREACT of "drop".
get "Get" transforms itself into "take" then
calls the PREACT of "take".
take "Take" determines whether the sentence is
one like "Take all but the sword and the
shield". If it is then a list of objects
is built up which are then taken. If
not, the normal semantics apply. If the
programmer wants an action to be per-
formed by the "take" ACTION, the routine
TakeAct should be defined.
drop "drop" may be used in sentences like
"Drop all but the book." If it is so
used, a list of objects is created which
are then dropped. If the programmer
wants an action to be performed by the
"drop" ACTION, the routine DropAct should
be defined.
go If "go" is used in a sentence like "Go
north", the Verb is changed to "north"
and the Dobj and Iobj are set to NULL.
This only applies to the direction verbs
"north", "south", "east", "west",
"northeast", "southeast", "northwest",
"southwest", "up", and "down".
c 1987 Ross Cunniff and Tim Brengle
- 57 -
again If the standard actor action is in
effect, the Verb "again" will never be
called or seen by Objects since it is
replaced by the previous sentence.
In addition to declaring the preceding verbs,
standard.adl declares the following equivalences:
g = again;
z = wait;
l = look;
u = up;
d = down;
north = n;
south = s;
east = e;
west = w;
northeast = ne;
northwest = nw;
southeast = se;
southwest = sw;
put on = wear;
take off = remove;
turn on = light;
turn off = douse;
10.5. Routines
Standard.adl declares and defines the following Rou-
tines for use by the ADL programmer:
StdInit,
Reach,
See,
Lit,
Avail,
CheckAvail,
Expect,
Preact,
Looker,
Prompter,
TakeAct,
DropAct,
ActAction,
SaveSentence,
Dwimmer;
Their use is defined as follows:
StdInit (StdInit actor) should be executed in
START if the programmer desires that ALL
of the default routines be used. Actor
c 1987 Ross Cunniff and Tim Brengle
- 58 -
should be the name of the primary
interactive Actor in the scenario.
Reach (Reach object container) is TRUE if
object is contained in container and if
the player can reach the object. It is
FALSE otherwise. Note that this also
checks whether object is contained in
something which is contained in container
and so on.
See (See object container) is TRUE if object
is contained in container and the player
can see the object. It is FALSE other-
wise. This also checks containers inside
containers.
Lit (Lit) is TRUE if something is lighting
the player's location and FALSE other-
wise.
Avail (Avail object) is TRUE if the player can
see object (either in the room or in the
player's inventory) and can reach the
object. It is FALSE otherwise.
CheckAvail (CheckAvail) checks to see whether the
Dobj and Iobj typed by the player are
available. If not, an appropriate mes-
sage is printed and ($exit 1) is per-
formed.
Expect Expect is typically called by the PREACT
of a Verb. It looks at the current sen-
tence to see whether it is of acceptable
form. The two parameters to Expect
define criteria for acceptability. The
first parameter indicates what types of
direct objects are acceptable and the
second indicates what types of indirect
objects are acceptable. Each parameter
consists of one or more of the Expect
flags $or'd together. The flag NO_OBJ
indicates that it is acceptable that no
object be present; ONE_OBJ indicates
that it is acceptable that one object be
present; MULT_OBJ indicates that it is
acceptable that multiple objects be
present; STR_OBJ indicates that it's OK
for the object(s) to be strings; and
PLAIN_OBJ indicates that it's OK for the
object(s) to be normal ADL objects.
Example:
c 1987 Ross Cunniff and Tim Brengle
- 59 -
{ "take" needs 1 to N Dobjs and 0 or 1 Iobjs }
take(PREACT) =
(Expect ($or MULT_OBJ PLAIN_OBJ)
($or NO_OBJ ONE_OBJ PLAIN_OBJ))
;
{ "quit" can accept no objects }
quit(PREACT) =
(Expect NO_OBJ NO_OBJ)
;
{ "unlock" needs exactly one Dobj and Iobj }
unlock(PREACT) =
(Expect ($or ONE_OBJ PLAIN_OBJ)
($or ONE_OBJ PLAIN_OBJ) )
;
{ "say" needs a string to say and possibly
someone to whom to say it }
say(PREACT) =
(Expect ($or ONE_OBJ STR_OBJ)
($or NO_OBJ ONE_OBJ PLAIN_OBJ))
;
Preact Preact is the standard PREACT for Verbs.
It checks to make sure that exactly one
plain Direct Object was typed and that
the Indirect Object is not a string. It
also checks to see whether all of the
named objects are available.
Looker Looker is the standard looking daemon.
It is intended to be executed every turn.
To enable this, either of the statements
($sdem Looker) or (StdInit actor) must be
executed (where actor) is the primary
actor).
Prompter Prompter is the standard prompting rou-
tine. To use it, either of the state-
ments ($prompt Prompter) or (StdInit
actor) must be executed.
ActAction ActAction is the standard Actor action.
It checks to see whether the Verb "again"
or the Object "it" was used and modifies
the sentences appropriately. To use it,
either of the statements ($setp .ME
ACTION ActAction) or (StdInit actor) must
be executed.
TakeAct TakeAct is called by the default action
routine of the Verb "take" after the
ACTION routines of all of the Direct
Objects have been executed.
c 1987 Ross Cunniff and Tim Brengle
- 60 -
DropAct DropAct is similar to TakeAct, except
that it is called by the ACTION routine
of "drop".
SaveSentence SaveSentence should be called by the ADL
programmer if it is desired that the Verb
"again" and the Object "it" work as in
ActAction above. Looker calls SaveSen-
tence every turn.
Dwimmer Dwimmer is the standard DWIMming routine.
It checks to see whether an ambiguous
object could possibly be the one the
player meant. To use Dwimmer, include
the statement (IF (Dwimmer %1) THEN
($return 1)) in DWIMI and/or DWIMD.
c 1987 Ross Cunniff and Tim Brengle
- 61 -
Appendix 1 - A Tiny Dungeon
The following dungeon is a tiny but complete scenario.
It demonstrates the use of $hit and $miss, as well as the
use of some of the features of standard.adl.
INCLUDE "standard.adl";
NOUN startrm, brightroom; { Locations in the dungeon }
startrm(LIGHT) = TRUE; brightroom(LIGHT) = TRUE;
cg = ($say "You can't go that way.\n");
startrm(LDESC) =
($say "You are in a small but comfortable room. You hardly "
"want to leave, but there is a door leading east, if "
"you insist.\n")
;
startrm (SDESC) = ($say "Comfortable room.\n");
startrm(ACTION) =
($miss cg cg 0 cg 0 0 0 0 0 0)
($hit .ME 0 0 brightroom 0 0 0 0 0 0 0)
;
brightroom(LDESC) =
($say "You are in a brightly lit room. The walls sparkle "
"with scintillating lights. There is a darker room "
"to the west.\n")
;
brightroom(SDESC) = ($say "Bright room.\n");
brightroom(ACTION) =
($miss cg cg cg 0 0 0 0 0 0 0)
($hit .ME 0 0 0 startrm 0 0 0 0 0 0)
;
ADJEC red, blue;
NOUN red pillow(startrm), blue pillow(startrm);
red pillow(LDESC) = ($say "There is a red pillow here.\n");
red pillow(SDESC) = ($say "A red pillow");
blue pillow(LDESC) = ($say "There is a blue pillow here.\n");
blue pillow(SDESC) = ($say "A blue pillow");
NOUN platinum(brightroom); bar = platinum;
platinum(LDESC) = ($say "There is a bar of platinum here!\n");
platinum(SDESC) = ($say "A platinum bar");
platinum(ACTION) =
(IF ($and ($eq ($verb) drop)
($eq ($loc .ME) ($loc [red pillow])))
THEN
($say "The bar falls onto the red pillow, breaking it! "
"The symbolism impresses itself upon you, and "
"you go back to work instead of playing these "
"silly games!\n")
($spec 3)
c 1987 Ross Cunniff and Tim Brengle
- 62 -
)
;
NOUN SELF(startrm); SELF(NOTAKE) = TRUE;
START = ($prompt Prompter)
($sdem Looker)
($actor SELF 0 1 0)
($setv n s e w 0 0 0 0 0 0)
;
DWIMD = ($return (DWIM %1));
DWIMI = (DWIM %1); { This result will be returned by default }
c 1987 Ross Cunniff and Tim Brengle
- 63 -
Appendix 2 - A scenario with multiple Actors
The following ADL program demonstrates both the use of
the standard package and the use of multiple actors. This
is the scenario which generated the script at the beginning
of this document.
INCLUDE "standard.adl"; { Include the standard package }
{ The following are Object properties }
BROKEN = 1; { Is the robot damaged? }
TOLD = 2; { Have I told the robot something? }
BSTATE = 17; { State of the button }
B_OFF = 0; { Button is off }
B_FLASH = 1; { Button is flashing }
B_LIT = 2; { Button is lit }
{ Global variables }
VAR
RobSave[ 6 ], { Saved sentence for the robot }
Score; { Current score }
{ Utility routines }
ROUTINE
NoGo, Sayer, Myself, Lifter,
DoorCk, TrapCk, RobMov, BlueCk,
Header, Die, Skore, RobEntr,
HatchSD;
{ Locations in the dungeon }
NOUN
Redrm, Bluerm,
Greenrm, Cellar,
Endrm;
{ Immovable objects }
NOUN
button( Bluerm ),
door( Cellar ),
hatch( Bluerm );
{ Objects which may become actors }
c 1987 Ross Cunniff and Tim Brengle
- 64 -
NOUN
me( Redrm ),
robot( Greenrm );
me( NOTAKE ) = TRUE;
{ Room descriptions }
Redrm( LDESC ) =
($say
"You are in a large room which is illuminated by a bright
red glow. Exits lie to the east and south.\n"
)
;
Redrm( SDESC ) = ($return (Header "Red room" %0));
Redrm( LIGHT ) = TRUE;
Greenrm( LDESC ) =
($say
"You are in a smallish room which is illuminated by a pleasant
green glow. The only exit is to the west.\n"
)
;
Greenrm( SDESC ) = ($return (Header "Green room" %0));
Greenrm( LIGHT ) = TRUE;
Bluerm( LDESC ) =
($say
"You are in a tiny room which is barely illuminated by a
dim blue glow. There is an exit to the north,"
)
(IF ($eq ($prop button BSTATE) B_LIT) THEN
($say
" and most of the floor has tilted up to reveal a hatch leading
down into blackness. A button on the wall is glowing brightly."
)
ELSE
($say " and you seem to make out something on the floor.")
(IF ($prop button BSTATE) THEN
($say " A button on the wall is flashing urgently.")
ELSE
($say " There is a button on the wall.")
)
)
($say
" Above the button is a sign that reads:\n\n"
" DANGER!\n\n"
" HIGH VOLTAGE!\n\n"
)
;
Bluerm( SDESC ) =
c 1987 Ross Cunniff and Tim Brengle
- 65 -
(IF %0 THEN ($return "Blue room"))
($say "Blue room.\n")
;
Bluerm( LIGHT ) = TRUE;
Cellar( LDESC ) =
($say
"You are in the cellar. Far above you can be seen a dim
blue light."
)
(IF ($prop door OPENED) THEN
($say
" An open door leads to the north.\n"
)
ELSE
($say
" You can barely see the outline of a door to the north.\n"
)
)
;
Cellar( SDESC ) =
($return (Header "Cellar" %0))
;
Cellar( LIGHT ) = TRUE;
Endrm( LDESC ) =
($say
"You exit from the dark cellar into a land filled with singing birds,
blooming flowers, flowing streams, and bright blue skies. In other words,
you have finished this game!\n"
)
($setg Score ($plus @Score 25))
(Skore)
($spec 3)
;
Endrm( LIGHT ) = TRUE;
{ Verbs }
VERB
score,
push,
shout;
tell = TELLER;
say = tell;
press = push;
feel = touch;
yell = shout;
c 1987 Ross Cunniff and Tim Brengle
- 66 -
{ Verb routines }
tell( PREACT ) =
(IF ($ne @Iobj robot) THEN
{ The only logical thing to talk to is the robot }
(Sayer
"Talking to yourself is said to be a sign of impending insanity"
)
ELSEIF ($ge @Dobj 0) THEN
{ You must say strings }
(Sayer
"You must put what you want to say in quotes"
)
ELSEIF ($ne ($loc robot) ($loc me)) THEN
{ The robot must be in the same place as the player }
(IF (Myself) THEN
($say "You don't see the robot here.\n")
)
ELSE
{ Everything is OK. Add 25 points to the score }
(IF ($not ($prop robot TOLD)) THEN
($setg Score ($plus @Score 25))
($setp robot TOLD TRUE)
)
($exit 0)
)
($exit 1)
;
tell( ACTION ) =
{ Tell the player that we heard him }
($say "\"Sure thing, Boss.\"\n")
{ Delete the old action }
($delact robot)
{ Add the new action - a non-interactive actor }
($actor robot @Dobj FALSE)
;
shout( PREACT ) =
(IF ($and @Iobj ($ne @Iobj robot)) THEN
{ Shouting at things other than the robot }
($say "AAARRRGGGHHH!\n")
ELSEIF ($ge @Dobj 0) THEN
{ Shouting things other than strings }
($say "EEEYYYAAAHHH!\n")
ELSEIF ($prop robot BROKEN) THEN
($say "There is no response.\n")
ELSE
{ Shouting at the robot - same as telling the robot }
(IF ($not ($prop robot TOLD)) THEN
($setg Score ($plus @Score 25))
($setp robot TOLD TRUE)
c 1987 Ross Cunniff and Tim Brengle
- 67 -
)
($exit 0)
)
($exit 1)
;
shout( ACTION ) =
{ Tell the player we heard him }
(IF ($ne ($loc robot) ($loc me)) THEN
($say "In the distance you hear the words, ")
)
($say "\"Sure thing, Boss\"\n")
{ Delete the old robot action }
($delact robot)
{ Add the new robot action }
($actor robot @Dobj FALSE)
;
push( PREACT ) =
{ Expect a plain direct object }
(Expect ($or ONE_OBJ PLAIN_OBJ) NO_OBJ)
(CheckAvail)
;
push( ACTION ) =
(Sayer "That doesn't seem to do anything")
($exit 1)
;
score(PREACT) =
{ Score can accept no objects }
(Expect NO_OBJ NO_OBJ)
(Skore)
($exit 1)
;
{ Object properties }
button( SDESC ) =
(IF ($eq ($prop button BSTATE) B_OFF) THEN
($say "a button")
ELSEIF ($eq ($prop button BSTATE) B_FLASH) THEN
($say "an urgently flashing button")
ELSE
($say "a brightly lit button")
)
;
button( ACTION ) =
(IF ($and (Myself)
($or ($eq @Verb push)
($eq @Verb take)
c 1987 Ross Cunniff and Tim Brengle
- 68 -
($eq @Verb touch)
)
)
THEN
{ The player tried to do something with the button }
($say
"As you reach for the button, a 10,000,000 volt bolt of lightning
arcs toward your finger, disintegrating you upon impact.\n"
)
(Die)
ELSEIF ($and ($eq @Verb push) ($eq ($prop button BSTATE) B_OFF)) THEN
{ The robot pushed the button }
($setp button BSTATE B_FLASH)
($setg Score ($plus @Score 50))
($sfus me Lifter 4)
($exit 1)
ELSEIF ($eq @Verb take) THEN
{ Can't take the button }
($setg Skip TRUE)
)
;
SimpleRobot = "I am just a simple robot";
robot( LDESC ) = ($say "There is a robot here.\n");
robot( SDESC ) = ($say "a robot");
robot( ACTION ) =
(IF (Myself) THEN
{ I'm doing something with the robot }
(IF ($eq @Verb tell) THEN
(IF ($prop robot BROKEN) THEN
($say "There is no response.\n")
($exit 1)
)
ELSEIF ($eq @Verb take) THEN
($say "The robot weighs at least 500 pounds!\n")
($exit 1)
)
ELSEIF ($eq ($phase) 2) THEN
{ This is being called as the Actor ACTION }
(ActAction)
(IF ($and ($ne @Verb push)
($ne @Verb go)
($ne @Verb wait)
($ne @Verb take)
($or ($lt @Verb north) ($gt @Verb down)))
THEN
{ The robot has a VERY simple vocabulary }
(Sayer SimpleRobot)
($delact robot)
($exit 1)
)
ELSEIF ($eq @Verb take) THEN
{ The robot is trying to take itself }
c 1987 Ross Cunniff and Tim Brengle
- 69 -
(Sayer "Mmmph! Akkk!! GGGGRR!! No can do. Sorry")
($setg Skip TRUE)
ELSE
{ The robot is doing something to itself }
(Sayer SimpleRobot)
($delact robot)
($exit 1)
)
;
robot( SAVESENT ) = RobSave;
{ We break me( ACTION ) out into a named routine because
StdInit overwrites that property and we need to restore it }
MeAct =
(IF ($eq ($phase) 2) THEN
{ This is the Actor ACTION - call standard's actor action }
(ActAction)
ELSEIF ($eq @Verb take) THEN
(Sayer "I thought you would never ask")
($setg Skip TRUE)
)
;
{ We break hatch( SDESC ) out into a named routine because
the hatch isn't visible until after Lifter has executed }
HatchSD = ($say "an open hatch");
HatchMSG = "The hatch doesn't budge";
hatch( ACTION ) =
(IF ($eq @Verb take) THEN
{ Can't take the hatch }
(Sayer HatchMSG)
($setg Skip TRUE)
ELSEIF ($or ($eq @Verb open) ($eq @Verb push)) THEN
{ Can't open or push it, either }
(Sayer HatchMSG)
($exit 1)
)
;
hatch( OPENS ) = TRUE;
hatch( NOTAKE ) = TRUE;
door( SDESC ) = ($say "a door");
door( ACTION ) =
(IF ($eq @Verb take) THEN
($say "You can't take a door!\n")
($setg Skip TRUE)
)
;
c 1987 Ross Cunniff and Tim Brengle
- 70 -
door( OPENS ) = TRUE;
{ Transition routines. Note that RobMov is used in $miss.
This produces the 'The robot exits to the <direction>
messages. The calls to RobEntr produce the messages like
'The robot enters from the <direction>. }
Bluerm( ACTION ) =
($miss RobMov NoGo NoGo NoGo NoGo TrapCk 0 0 0 0)
($hit .ME Redrm 0 0 0 0 Cellar 0 0 0 0)
(RobEntr)
;
Redrm( ACTION ) =
($miss NoGo BlueCk RobMov NoGo NoGo NoGo 0 0 0 0)
($hit .ME 0 Bluerm Greenrm 0 0 0 0 0 0 0)
(RobEntr)
;
Greenrm( ACTION ) =
($miss NoGo NoGo NoGo RobMov NoGo NoGo 0 0 0 0)
($hit .ME 0 0 0 Redrm 0 0 0 0 0 0)
(RobEntr)
;
Cellar( ACTION ) =
($miss DoorCk NoGo NoGo NoGo BlueCk NoGo 0 0 0 0)
($hit .ME Endrm 0 0 0 Bluerm 0 0 0 0 0)
(RobEntr)
;
{ Routines }
{ (Myself) - returns 1 if "me" is the current actor; 0 otherwise }
Myself =
($return ($eq .ME me))
;
{ (Sayer str) - Says a string with appropriate quoting, depending
on whether the robot or the player is doing the saying. }
Sayer =
(IF (Myself) THEN
($say %1 ".\n")
ELSEIF ($eq ($loc robot) ($loc me)) THEN
($say "\"" %1 ", Boss.\"\n")
ELSE
($say "You hear a muffled voice in the distance.\n")
)
c 1987 Ross Cunniff and Tim Brengle
- 71 -
;
{ (NoGo) - "You can't go that way" }
NoGo =
(Sayer "You can't go that way")
($exit 1)
;
{ (Header str arg0) - To accomplish the printing of header lines,
each location SDESC need to return a string if a parameter is
passed to it. By doing ($return (Header <sdesc> %0)), we can
centralize the saying/returning decision. }
Header =
(IF ($not %2) THEN
($say %1 ".\n")
)
($return %1)
;
RobMov =
(IF ($and ($not (Myself)) ($eq ($loc robot) ($loc me))) THEN
($say
"The robot exits to the "
(IF ($eq @Verb e) THEN
($val "east")
ELSEIF ($eq @Verb w) THEN
($val "west")
ELSEIF ($eq @Verb s) THEN
($val "south")
{ The robot can't be seen leaving to the north }
)
".\n"
)
)
;
RobEntr =
(IF ($and ($not (Myself)) ($eq ($loc robot ) ($loc me))) THEN
($say
(IF ($eq @Verb north) THEN
($val "The robot enters from the south.\n")
ELSEIF ($eq @Verb east) THEN
($val "The robot enters from the west.\n")
ELSEIF ($eq @Verb west) THEN
($val "The robot enters from the east.\n")
{ The robot can't enter from the north in
this scenario }
)
)
)
c 1987 Ross Cunniff and Tim Brengle
- 72 -
;
DoorCk =
(IF ($not ($prop door OPENED)) THEN
($say "The door seems to be closed.\n")
($exit 1)
)
;
TrapCk =
(IF ($ne ($prop button BSTATE) B_LIT) THEN
(NoGo)
)
;
{ (BlueCk) - make sure that only one actor is in the blue room
at one time. }
BlueCk =
(IF ($or ($eq ($loc me) Bluerm) ($eq ($loc robot) Bluerm)) THEN
(IF (Myself) THEN
($say
"The room is too small for both you and the robot to fit.\n"
)
)
($exit 1)
ELSEIF ($and ($not (Myself)) ($eq ($prop button BSTATE) B_LIT)) THEN
(RobMov)
($say "You hear a loud CRASH! in the distance.\n")
($setg Score ($minus @Score 10))
($setp robot BROKEN TRUE)
($move robot Bluerm)
($delact robot)
($exit 1)
)
(RobMov)
;
{ (Die) - kill off the player }
Die =
($setg Score ($minus @Score 50))
(Skore)
($say "Do you wish to restart the game? ")
(IF ($yorn) THEN
($spec 2)
ELSE
($spec 3)
)
;
c 1987 Ross Cunniff and Tim Brengle
- 73 -
{ (Lifter) - Lift the hatch, possibly killing the robot or
the player }
Lifter =
(IF ($eq ($loc me) Bluerm) THEN
($say
"All of a sudden, the floor lifts up, and you are crushed between it
and the wall! "
)
(Die)
ELSE
($say "In the distance, you hear a loud CRASH!\n")
(IF ($eq ($loc robot) Bluerm) THEN
($setg Score ($minus @Score 10))
($setp robot BROKEN TRUE)
($delact robot)
)
)
($setp hatch SDESC HatchSD)
($setp button BSTATE B_LIT)
($setp Bluerm SEEN FALSE)
;
{ Prompt - print the status line and a prompt }
PROMPT =
($spec 9 (($sdesc ($loc .ME)) 1) @Score ($turns))
($say "> ")
;
{ Increment - increment the turn counter }
INCREMENT =
(IF (Myself) THEN
{ We only want to increment once per turn }
($incturn)
ELSE
{ We don't want Looker executing for the robot }
($exit 0)
)
;
{ (Skore) - print out the current score. }
Skore =
($say "You have scored " ($str @Score)
" out of a possible 100 in " ($str ($turns)) " moves.\n")
;
{ Dwimming routines }
DWIMI = (Dwimmer %1);
DWIMD = (Dwimmer %1);
START =
c 1987 Ross Cunniff and Tim Brengle
- 74 -
($spec MARGIN 69) { Set the screen to 69 wide }
($sdem INCREMENT) { Turn counter increment }
(StdInit me) { Initialize standard }
($setp me ACTION MeAct) { Restore me( ACTION ) }
($setv n s e w u d 0 0 0 0) { Use our own transition vector }
($prompt PROMPT) { and our own prompter }
($setg Indent TRUE) { Indent the object descriptions }
;
{*** EOF actdemo.adl ***}
c 1987 Ross Cunniff and Tim Brengle
- 75 -
Appendix 3 - Glossary
Actor An Actor in ADL is similar to an Actor in a
play, in that the Actor has a script to fol-
low (the lines typed by the player), and
there may be more than one Actor acting at a
time.
Adjective An adjective is a part of speech which
describes a noun. "Red", "green", "big",
and "rusty" are all adjectives.
Argument An argument to an ADL routine is one of the
list of "things" which the routine was told
to operate on. For example, in the routine
call ($plus 20 30 40) the first argument is
20, the second argument is 30, and the third
argument is 40.
Article An article is a part of speech which often
conveys some sense of "definiteness". "The"
is an article, as are "a" and "an". ADL
ignores articles in player sentences, so
their proper use is of little importance.
ASCII ASCII (which stands for American Standard
Code for Information Interchange, as if you
really wanted to know) is a method of
representing characters (such as "a", "b",
"9", etc.) as numbers for the purpose of
computer manipulation. Thus, the ASCII
representation of the letter "A" is 65. The
expression "the ASCII representation of the
number 45308" is often heard. This means
that the number 45308 is represented as the
ASCII string "45308". This is slightly dif-
ferent than the ASCII code of a character.
BNF BNF is a method of representing the syntax
of a language in a concise way. In English,
one may say that "A list is a sequence of
things." In BNF, one may say that "list =
thing *" which means that a list consists of
zero or more things. (This is actually an
extended form of BNF which is more concise
than the original). Other things one may
say include "foo = bar +" which means that
foo consists of one or more bars; "bletch =
[ ack ] gag" which means that a bletch is an
optional ack followed by a gag. Parentheses
may be used for grouping; for example "abcbc
= a ( b c ) *" means that an abcbc is an "a"
followed by zero or more occurrences of the
two-element list "b c".
c 1987 Ross Cunniff and Tim Brengle
- 76 -
Buffer See Line Buffer.
Conjunction A conjunction is a part of speech which is
used to join two parts of a sentence
together. Conjunctions include the word
"and", the word "but", and the comma ",".
Container A container is an object which contains
another object, just as in real life.
Daemon A daemon is a routine which is executed
periodically. For example, in real life Joe
Blow goes on a coffee break every 15
minutes. A coffee break could then be con-
sidered a daemon which executes every 15
minutes (and Joe Blow could be considered
lazy). ADL daemons execute once every turn.
Direct Object A direct object is a part of speech on which
the verb is "acting" directly. For example,
in the sentence "Take the food" the word
"food" is the direct object. Direct objects
may consist of more than one word.
Fuse A fuse is similar to a daemon except that
instead of being executed periodically, it
waits a for some time to pass then executes
exactly once. For example, in real life
setting your alarm to go off at six o'clock
in the morning could be considered activat-
ing a fuse.
Global See Variable.
Global Variable See Variable.
Implementor The implementor is the person who wrote the
ADL compiler and ADL interpreter which run
on your computer. Send the implementor lots
of praise and/or money.
Indirect Object An indirect object is a part of speech which
is indirectly acted upon by the verb. For
example, in the sentence "Take the rock from
the stream", "stream" is the indirect object
as it is not directly affected by the verb
"take". Usually an indirect object is pre-
ceded by a preposition. There is one case
where it is not. For example, in the sen-
tence "Give the frog the bait" it is the
bait which is being given. This may seem
confusing but if you rewrite the sentence as
"Give the bait to the frog" it makes more
sense.
c 1987 Ross Cunniff and Tim Brengle
- 77 -
Line Buffer A line buffer is an area in the memory of
the computer where the last line which was
typed by a player is stored. Words which
are read by the Parser are read from this
buffer, not directly from the keyboard.
Local Variable See Variable.
Location The location of some specified object is the
object which contains the specified object.
Modifier A modifier is a part of speech which is
essentially the same as an adjective in
function. ADL allows some verbs to act as
modifiers in order to better mimic the
English language.
Noun A noun is a person, place, or thing. A desk
is a noun. America is a noun. Fred Rogers
is a noun. "Noun" and "object" are normally
interchangeable terms. Usually however,
when a reference is made to something being
a "noun" it implies that something is just
one word (as in "desk"), and not two words
(as in "blue streak").
Object See Noun.
Parse Parsing is the process of breaking down an
input string into structured data. For
example, parsing the string "Take the green
brick and the nail from the wall" would
parse into the verb "Take", the direct
objects "green brick" and "nail", the prepo-
sition "from", and the indirect object
"wall".
Player A player is a person who plays a game. Gen-
erally, a player is associated with an Actor
in an ADL scenario.
Preposition A preposition is a part of speech which
often specifies some location (like "under"
or "beside") or some destination (like "in"
or "on"). Prepositions are generally found
before Indirect Objects in sentences, but
occasionally modify Verbs.
Prompt A prompt is some sort of message from the
computer to a human indicating that some
input is expected.
Programmer The programmer (in this documentation, at
least) is the person who created the game
c 1987 Ross Cunniff and Tim Brengle
- 78 -
scenario which is compiled and interpreted
by ADL. Send the programmer lots of praise
and/or money too.
Room A room is any object that a player may even-
tually enter.
Routine A routine is a series of instructions to the
computer telling it what to say, what to
move, what to read, and/or where to go.
Scenario A "scenario" is like a scene in a play - it
specifies where Objects are located, what
events might occur, who is present, and what
they may do. A scenario is somewhat more
general than a scene since scenarios contain
rules for generating many possible scenes
whereas scenes are static.
Separator A separator is a part of speech which
separates two sentences. A separator can be
a period ".", the word "then", or the end of
a line.
String A string is a series of characters (letters,
etc.) surrounded by quote marks. "foo bar
bletch" is a string (legal in both the com-
pilation and execution phases of ADL) and
'Hi, there!' is a string (legal only in the
execution phase of ADL).
Stack A stack is like a stack of dishes: you may
put a new dish on top of the stack (this is
known as "pushing") or you may take a dish
from the top of the stack (this is known as
"popping"). You may not take dishes from
the bottom or middle of the stack; likewise,
a computer stack doesn't allow the deletion
of elements in the middle of the stack.
Syntax The syntax of a language is the set of rules
which say how things may be put together in
order to make a valid program in that
language.
User See Player.
Variable A variable is a location in the memory of a
computer in which values may be stored,
changed, and erased. Global variables (or
globals for short) are variables which are
directly accessible by name to all routines
of an ADL program. Local variables (or
locals) are variables which are only
c 1987 Ross Cunniff and Tim Brengle
- 79 -
directly accessible by the routine in which
they are named. They are only indirectly
accessible by other routines.
Verb A verb is a part of speech which implies
some action. "Take", "run", "eat", "sleep",
and "hide" are all verbs.
c 1987 Ross Cunniff and Tim Brengle
Table of Contents
1. Introduction ---------------------------------- 1
2. ADL Data types -------------------------------- 3
2.1. Objects ---------------------------------- 3
2.2. Verbs ---------------------------------- 4
2.3. Adjectives ---------------------------------- 5
2.4. Strings ---------------------------------- 5
2.5. Numbers ---------------------------------- 5
2.6. Routines ---------------------------------- 6
2.7. Global Variables ---------------------------- 6
2.8. Local variables ----------------------------- 6
2.9. Modifiers ---------------------------------- 6
3. ADL Internal Structures ----------------------- 7
3.1. Actors ---------------------------------- 7
3.2. Daemons ---------------------------------- 8
3.3. Fuses ---------------------------------- 8
3.4. Prompter ---------------------------------- 8
3.5. Run-Time Macros ----------------------------- 8
4. Putting It All Together ----------------------- 10
4.1. The Flow of Execution ----------------------- 10
4.2. $exit ---------------------------------- 13
5. ADL Programs ---------------------------------- 15
6. Routines ---------------------------------- 20
7. ADL Built-in Routines ------------------------- 23
7.1. Object Routines ----------------------------- 24
7.2. Verb Routines ------------------------------- 27
7.3. Arithmetic Routines ------------------------- 28
7.4. Boolean Routines ---------------------------- 29
7.5. Global Value Routines ----------------------- 32
7.6. Transition Routines ------------------------- 34
7.7. String Manipulation Routines ---------------- 35
7.8. Name Routines ------------------------------- 38
7.9. Conversion Routines ------------------------- 39
7.10. Internal Structure Manipulation Routines --- 40
7.11. Special Routines --------------------------- 43
7.12. Miscellaneous Routines --------------------- 46
8. ADL Program Structure ------------------------- 49
9. ADL Sentence Structure ------------------------ 51
10. standard.adl --------------------------------- 52
10.1. Object properties -------------------------- 52
10.2. Constants ---------------------------------- 53
10.3. Words ---------------------------------- 55
10.4. Verbs and their actions -------------------- 55
10.5. Routines ---------------------------------- 57
Appendix 1 - A Tiny Dungeon ----------------------- 61
Appendix 2 - A scenario with multiple Actors ------ 63
Appendix 3 - Glossary ----------------------------- 75
c 1987 Ross Cunniff and Tim Brengle